Introduction

In the previous topics, we have explored ways to produce various type of graphs. However all of them (with the exception of mapview) are static. In this topic, we will discuss some methods that can be used to make visuals produced using R and ggplot2 to be interactive by introducing hover effect, tooltip, and click effect. Interactive visuals are great if you want to publish your visual in a website or blog, and readers can interact with the visuals, giving them more information when hovering and making the visuals more attractive.

As usual we load the important packages.

library(ggplot2)
library(dplyr)

Interactive Visualization with Plotly

One of the most popular libraries for interactive visualization in R is Plotly, which provides dynamic and customizable plots with ease. Unlike static visualizations, interactive plots allow users to hover over data points, zoom in and out, and filter data dynamically.

To use Plotly in R, you need to install the plotly package if you haven’t already:

install.packages("plotly") 

Then, load the package:

library(plotly) 

Creating basic interactive plots

Plotly in R works well with ggplot2, but it also allows users to create interactive plots from scratch using the plot_ly() function. If you want to use ggplot2, you can save the ggplot graph as an object and use ggplotly() function to convert it to Plotly graph.

Let’s create an interactive scatter plot using the mpg data set from ggplot2 package:

# Save the ggplot object as a variable
p <- ggplot(data = mpg, mapping=aes(x=displ, y=hwy, color=class)) +
  geom_point(alpha=0.75) +
  theme_minimal() +
  labs(x = "Engine displacement (L)",
       y = "Highway miles per gallon",
       color = "Vehicle type")

# Convert the ggplot object to plotly
ggplotly(p)

Notice that when you hover your mouse over the points, the mapping (x, y, color) of the points are shown in a tooltip. Notice also that on the top-right of the graph, there are some buttons you can click to download the plot as PNG, zoom in and out, and so on. Additionally, try clicking on a vehicle type in the legend to hide/show related points. You can also double click on a vehicle type in the legend to show data for that category only.

The tooltip can be customized using the text mapping in the aes() function, and using the tooltip argument in the ggplotly(). In the code below, the <br> is used to break the line using HTML format.

p <- ggplot(data = mpg, mapping=aes(x=displ, y=hwy, color=class,
                                    text=paste('Engine displacement:', displ,
                                               '<br>Highway mpg:', hwy,
                                               '<br>Vehicle type:', class))) +
  geom_point(alpha=0.75) +
  theme_minimal() +
  labs(x = "Engine displacement (L)",
       y = "Highway miles per gallon",
       color = "Vehicle type")

ggplotly(p, tooltip="text")

Alternatively, if we do not want to use ggplotly(), we can simply use the plot_ly() function to create a Plotly graph.

# Create a scatter plot
fig <- plot_ly(data = mpg,
               x = ~displ,
               y = ~hwy,
               type = 'scatter',
               marker = list(size = 10, color = 'blue'))

# Display the plot
fig 

In this example, type = 'scatter' specifies a scatter plot, and the marker argument customizes point size and color.

Here is another example with interactive line plot using the economics data set from ggplot2.

p <- ggplot(data = economics, mapping = aes(x=date, y=unemploy)) +
  geom_line(color="red") +
  theme_minimal() +
  labs(x="Date", y="Unemployment (thousands)")

ggplotly(p)

By default, the hover label appears at the nearest point in the chart. But for a line chart, you can change the hover mode so that it follows the x-axis for multiple graphs. This can be done by saving the Plotly object to a variable and using hovermode="x" in the layout function.

library(dslabs)

# Filter the data for Malaysia and Singapore only
regional_data <- filter(gapminder, country %in% c("Malaysia","Singapore"))

# Save the ggplot object to a variable
p <- ggplot(data=regional_data, mapping=aes(x=year, y=fertility, color=country)) +
  geom_line() +
  theme_minimal()

# Convert the ggplot object to plotly
p2 <- ggplotly(p)

# Change the plotly layput so that mouse hover follows x-axis
layout(p2, hovermode="x")

Facets

Since Plotly works with ggplot2, the interactivity also works when facetting. In the output below, a tooltip appear when you hover your mouse over points. Then, if you zoom-in, both the left and right facets will be zoomed it at the same region.

mpg2 <- mpg %>%
  mutate(trans=ifelse(substring(trans,1,1) == "a", "auto", "manual"))

p <- ggplot(data = mpg2, mapping = aes(x=displ, y=hwy, color=class)) +
  geom_point(alpha=0.75) +
  facet_wrap(~trans)+
  labs(x = "Engine displacement (L)",
       y = "Highway miles per gallon",
       color = "Vehicle type")

ggplotly(p)

Interactive Visualization with ggiraph Package

Another useful package in R is the ggiraph package which extends the widely used ggplot2 package by enabling interactivity in an easy-to-use framework. ggiraph essentially wraps your ggplot2 objects, injecting JavaScript code that enables features like tooltips, hover effects, and click actions.

Before diving into examples, ensure you have installed the ggiraph package:

install.packages("ggiraph")

Then, load it into your R session:

library(ggiraph)

The ggiraph package builds upon ggplot2 by adding interactive features through the geom_ functions. These enhanced geoms allow users to incorporate tooltips, hyperlinks, and hover effects seamlessly.

A quick example with ggiraph

The core principle involves adding aesthetic mappings related to interactivity. These mappings, like tooltip and onclick, are then translated into interactive behavior by ggiraph.

To use ggiraph with ggplot2 for interactive plots, we first use ggplot() function to specify the data and mapping. Then, when calling the geom function, we need to add _interactive at the end of the function name. Save the ggplot object to a variable, and use the girafe() function with the argument ggobj equal to the ggplot object.

Consider a simple scatter plot:

# Save the ggplot object
p <- ggplot(data=mpg, mapping=aes(x=displ, y=hwy, color=class,
                                  tooltip=manufacturer)) +
  
  # Use interactive version of geom_point
  geom_point_interactive() +
  
  theme_minimal()

# Create interactive graphic using ggplot object
girafe(ggobj = p,
       options = list(opts_sizing(rescale = FALSE)))

In the example above,

  • geom_point_interactive() is used instead of geom_point(), allowing for tooltip interactions.

  • The tooltip aesthetic is mapped to manufacturer, showing the car’s manufacturer when hovering over a point.

  • ggiraph() renders the ggplot object as an interactive graphic. The options argument is included for sizing the plot in HTML page for readability.

When you move your mouse or cursor to a point, notice that a tooltip appears that shows you the manufacturer’s name.

Customizing the tooltip

Similar to Plotly, we can modify the tooltip option in the mapping using HTML code if we want to customize it. Note that in the code below, another options is added to the girafe() function to change the background color of the tooltip.

p <- ggplot(data=mpg, mapping=aes(x=displ, y=hwy, color=class,
                                  tooltip=paste("Engine displacement:", displ,
                                                "<br>Manufacturer:", manufacturer))) +
  geom_point_interactive() +
  theme_minimal()

girafe(ggobj = p,
       options = list(opts_sizing(rescale = FALSE),
                      opts_tooltip(use_fill = TRUE)))

Enhancing interactivity with hover effects

We can enhance this plot by adding hover effects, such as changing the point’s size and color. But this require adding the data_id option in the aes() mapping.The css argument in the opts_hover() function can be used to modify the effect (color, size, etc) using CSS format.

Additionally, we can add hover_nearest = TRUE in the interactive geom_ function, which applies the hover effect to the nearest point/element of the mouse, even if the mouse is not exactly on the point. The nearest_distance argument in opts_hover() controls the distance for the hover effect to take place, if hover_nearest = TRUE is used.

# Save ggplot object
p <- ggplot(data=mpg, mapping=aes(x=displ, y=hwy, color=class,
                                  tooltip=manufacturer, data_id=manufacturer)) +
  
  # Use interactive geom_point
  # Make the mouse hover interacts with the nearest point
  geom_point_interactive(hover_nearest = TRUE) +
  theme_minimal()

girafe(ggobj = p,
       
       # Change the CSS style of points to 5px and red when hovered
       options = list(opts_hover(css = "r:5px;fill:red;",
                                 nearest_distance = 20),
                      opts_sizing(rescale = FALSE)))

Notice that when your mouse or cursor hovers close to a point, the point together with other points with similar manufacturer are highlighted in red and bigger size. Here, opts_hover changes the radius (r) and fill color of the points when the mouse hovers over them. The data_id mapping is important to tell ggiraph to identify the points.

Adding click actions

You can also add hyperlinks to points, making them clickable. Here’s an example where each point links to a Google search for the respective car manufacturer.

p <- ggplot(data=mpg, mapping=aes(x=displ, y=hwy, color=class,
                                  tooltip=manufacturer, data_id=manufacturer,
                                  )) +
  
  # Specify onlick behaviour to open new windows for google search
  geom_point_interactive(mapping=aes(
    onclick = paste0('window.open("https://www.google.com/search?q=',
                     manufacturer, '")'))) +
  theme_minimal()

girafe(ggobj = p,
       options = list(opts_hover(css = "r:5px;fill:red;"),
                      opts_sizing(rescale = FALSE)))

Facets and patchwork with ggiraph

The ggiraph also works with facet by highlighting points with similar data_id. Notice in the visual below, when hovering a point, all the points with the same vehicle class type on the left and right facets appear bigger as specified in opts_hover() function.

mpg2 <- mpg %>%
  mutate(trans=ifelse(substring(trans,1,1) == "a", "auto", "manual"))

p <- ggplot(data = mpg2, mapping = aes(x=displ, y=hwy, color=class,
                                       tooltip=class,
                                       data_id=class)) +
  geom_point_interactive(alpha=0.75) +
  facet_wrap(~trans)+
  labs(x = "Engine displacement (L)",
       y = "Highway miles per gallon",
       color = "Vehicle type")

girafe(ggobj = p,
       options = list(opts_hover(css = "r:5px;"),
                      opts_tooltip(use_fill = TRUE),
                      opts_sizing(rescale = FALSE)))

We have talked about using the patchwork package to combine multiple graphs into one plot. One good thing about ggiraph is that it allows for interaction with patchwork by linking the multiple graphs using the data_id mapping.

In the code below, we use the gapminder data set from the gapminder package to create two graphs. Both graphs have the same data_id mapping, which is the name of the country. When hovering a bar on either graph, the corresponding bar with the same data_id is highlighted in the other graph.

library(patchwork)
library(gapminder)

df1 <- filter(gapminder, year == 1997 & continent=="Asia")
df2 <- filter(gapminder, year == 2007 & continent=="Asia")

p1 <- ggplot(data=df1, mapping=aes(x=lifeExp, y=reorder(country,lifeExp),
                                   tooltip=lifeExp,
                                   data_id=country)) +
  geom_bar_interactive(stat="identity", fill="steelblue") + 
  labs(x="1997", y="Country")
  

p2 <- ggplot(data=df2, mapping=aes(x=lifeExp, y=reorder(country,lifeExp),
                                   tooltip=lifeExp,
                                   data_id=country)) +
  geom_bar_interactive(stat="identity", fill="steelblue") +
  labs(x="2007", y="")

p <- p1+p2 &
  theme_minimal() &
  theme(panel.grid.major.y = element_blank())

girafe(code = print(p), options = list(opts_sizing(rescale = FALSE)))

Interactive Tables with DT package

Data visualization is a crucial part of data analysis, but sometimes a well-structured, interactive table is just as powerful as a graph. The DT package in R provides an elegant way to transform static tables into dynamic, user-friendly displays, making it easier to explore and analyze data.

The DT package is an interface to the JavaScript DataTables (https://datatables.net/) library. It allows users to create tables with interactive features such as searching, sorting, filtering, and pagination, all within an R environment. The DT package is particularly useful when working with large datasets, as it enhances accessibility and usability without requiring external software.

First, ensure you have the package installed:

install.packages(DT)

Then, load the package.

library(DT)

Creating a basic interactive table

Once the necessary packages are loaded, creating an interactive table is straightforward. Use the datatable() function from DT:

datatable(gapminder)

This command generates an interactive table where users can:

  • Search for specific values.

  • Sort columns in ascending or descending order.

  • Paginate through the rows for easy navigation.

Filtering and highlighting data

For better data exploration, you can enable column-specific filtering and row highlighting:

{r} datatable(gapminder, filter = "top", rownames = FALSE)}

The filter = "top" argument adds a filter box to each column, allowing users to refine their search dynamically.

Customizing the table

The DT package allows for extensive customization. You can modify the table layout, set the number of rows displayed by default, enable or disable sorting, and even add export options. Below is an example with customized options:

datatable(gapminder,
          caption = "Countries demographic data from the gapminder data set",
          options = list(pageLength = 10,
                         autoWidth = TRUE,
                         dom = 'Bfrtip',
                         buttons = c('copy', 'csv', 'excel', 'pdf', 'print')),
          extensions = 'Buttons')

In the code above:

  • The dom = 'Brftip' in the options specify the elements we want in the table, which are Buttons, filtering input (the search filter), processing indicator (to show when table is being processed for example when sorting), table, table information summary (e.g. ‘Showing 1 to …’), and pagination control. For more info on this, you can check the dom section in the DataTables manual (https://datatables.net/reference/option/dom).

  • The default number of displayed rows is set to 10 using the pageLength = 10 line in the options.

  • Automatic column width adjustments is enabled using autoWidth = TRUE.

  • Export buttons for copying and saving the table in different formats (CSV, Excel, PDF, etc.) are added using the buttons argument in the options and extensions = 'Buttons' argument.

Selecting specific columns and rows

You can also select specific columns to display:

datatable(gapminder[, c("country", "year", "lifeExp", "gdpPercap")],
          filter = "top",
          options = list(pageLength = 5))

This displays only the country, year, lifeExp, and gdpPercap columns.

Saving Interactive Visuals to a HTML file

The htmlwidgets package serves as a crucial bridge between R and JavaScript libraries, enabling the creation of interactive web visualizations. A core function of this package is saveWidget(), which provides a straightforward way to save these interactive charts as standalone HTML files. This is essential for sharing and embedding interactive visualizations created with packages like plotly, ggiraph, and DT.

The saveWidget() function takes two primary arguments: the interactive widget object (e.g., a plotly plot, a girafe graphic, or a DT table) and the desired filename for the HTML output.

library(htmlwidgets)

# Example using a plotly chart
library(plotly)
p1 <- ggplot(data = mpg, mapping=aes(x=displ, y=hwy, color=class,
                                    text=paste('Engine displacement:', displ,
                                               '<br>Highway mpg:', hwy,
                                               '<br>Vehicle type:', class))) +
  geom_point(alpha=0.75) +
  theme_minimal() +
  labs(x = "Engine displacement (L)",
       y = "Highway miles per gallon",
       color = "Vehicle type")

p <- ggplotly(p1, tooltip="text")

# Save the visual as mpg_plotly.html
saveWidget(p, "mpg_plotly.html")
# Example using a ggiraph graphic
library(patchwork)
library(gapminder)

df1 <- filter(gapminder, year == 1997 & continent=="Asia")
df2 <- filter(gapminder, year == 2007 & continent=="Asia")

p1 <- ggplot(data=df1, mapping=aes(x=lifeExp, y=reorder(country,lifeExp),
                                   tooltip=lifeExp,
                                   data_id=country)) +
  geom_bar_interactive(stat="identity", fill="steelblue") + 
  labs(x="1997", y="Country")
  

p2 <- ggplot(data=df2, mapping=aes(x=lifeExp, y=reorder(country,lifeExp),
                                   tooltip=lifeExp,
                                   data_id=country)) +
  geom_bar_interactive(stat="identity", fill="steelblue") +
  labs(x="2007", y="")

p3 <- p1+p2 &
  theme_minimal() &
  theme(panel.grid.major.y = element_blank())

p <- girafe(code = print(p3), options = list(opts_sizing(rescale = FALSE)))

# Save the visual as gapminder_girafe.html
saveWidget(p, "gapminder_girafe.html")
# Example using a DT table
library(DT)
table <- datatable(gapminder[, c("country", "year", "lifeExp", "gdpPercap")],
          filter = "top",
          options = list(pageLength = 5))

# Save the table as gapminder_table.html
saveWidget(table, "gapminder_table.html")

The HTML file will be saved in your working directory. You can then share the files via email, upload to a website, or embed them within a blog post or web application.

Conclusion

This topic delves deep on creating interactive visualizations using R and several packages including plotly, ggiraph, and DT. Note that there are other packages you can use to make interactive graphs in R such as rbokeh, rCharts, highcharter, or dygraphs. You are free to read and explore on these other methods. After creating the interactive charts, you can save it to a HTML file to share or use it on a website.